package name.swingeet.swingElf;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryManagerMXBean;
import java.net.URISyntaxException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import name.swingeet.attach.SwingAgent;



import sun.jvmstat.monitor.MonitorException;
import sun.jvmstat.monitor.MonitoredHost;
import sun.jvmstat.monitor.MonitoredVm;
import sun.jvmstat.monitor.MonitoredVmUtil;
import sun.jvmstat.monitor.VmIdentifier;


import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.VirtualMachineDescriptor;

public class SwingTestClient {
	
	
	private String APP_MAINCLASS="";

	public void detach(String processName) throws Exception{
	
    	String id="";
    	int count=0;
    	
   
    	List<VirtualMachineDescriptor> vmds = VirtualMachine.list();
		for(VirtualMachineDescriptor vmd : vmds)
		{
		String appName=vmd.displayName();
		if(appName.indexOf(processName)>-1){
			id=vmd.id();
			break;
		}
		}

    	
    	MonitoredHost local = MonitoredHost.getMonitoredHost("localhost"); 	

    	MonitoredVm vm = local.getMonitoredVm(new VmIdentifier("//" + id));
    	vm.detach();
	}
		
	private String getAgentJVMHome(String cmd){
		
		 Process p;
		 String message="";
		    try {
	
		      p = Runtime.getRuntime().exec(cmd);
		      InputStream is = p.getInputStream();
		
		      InputStreamReader bi = new InputStreamReader(is);
		      BufferedReader br = new BufferedReader(bi);
		      
		      message =  br.readLine();      
		      while(message != null && !"".equals(message)){	
		        System.out.println(message);
		        if(message.indexOf("java.property.java.home")>-1)
		        	break;
		        message =  br.readLine();
		      }
		    } catch (Exception e) {
		      e.printStackTrace();
		
		    }
		    message=message.split("=")[1];
		    if(message.endsWith("\""))
		    	message=message.substring(0,message.length()-1);
		    message=message+File.separator+"bin"+File.separator+"java.exe\"";
		    return message;
	}
	/**
	 * Register to remote Agent.
	 * @return
	 * @throws RemoteException
	 * @throws NotBoundException
	 */
	public SwingTestInterface registerToAgent() throws RemoteException, NotBoundException{
    	Registry registry = LocateRegistry.getRegistry(1099);
    	SwingTestInterface sti=(SwingTestInterface)registry.lookup("Swingeet");
    	return sti;
	}
	/**
	 * Reference the class which is running in remote JVM
	 * Automated find the main class
	 * @param sti
	 * @throws Exception
	 */
	public void referenceAppClass(SwingTestInterface sti) throws Exception{
		sti.ReferenceApp(this.APP_MAINCLASS);
	}
	/**
	 * Reference to the class Which is running in remote JVM
	 * @param sti
	 * @param className
	 * @throws Exception
	 */
	public void referenceAppClass(SwingTestInterface sti,String className) throws Exception{
		
		sti.ReferenceApp(className);
	}
	/**
	 * Attach agent to the target JVM
	 * @param processName
	 * @param agentJar
	 * @return
	 * @throws Exception
	 */
	public boolean attachAgentToApp(String processName,String agentJar) throws Exception
	  {
		

		boolean isSuccessed=false;
	    	String id="";
	    	int count=0;
	    	while(count<50){

	        	
	    	List<VirtualMachineDescriptor> vmds = VirtualMachine.list();
			for(VirtualMachineDescriptor vmd : vmds)
			{
			String appName=vmd.displayName();
			if(appName.indexOf(processName)>-1){
				id=vmd.id();
				break;
			}
			}
			if(!id.equals("")) {
				System.out.println("Found the process has name key with '" +processName+"'. Process id"+id);
				break;
			}
			else {
			System.out.println("Could find the process has name key with '" +processName+"'. Waiting....");
				Thread.sleep(2000);
			}
	    	}
	    	
	    	if(id.equals(""))
	    		return isSuccessed;
	    	
	    	MonitoredHost local = MonitoredHost.getMonitoredHost("localhost"); 	

	    	MonitoredVm vm = local.getMonitoredVm(new VmIdentifier("//" + id));
	    	APP_MAINCLASS = MonitoredVmUtil.mainClass(vm, true);
	    	
	    	System.out.println(System.getProperty("java.home"));
	    	String java_home=System.getProperty("java.home");
	    	if(java_home.endsWith("jre"))
	    		java_home=java_home.substring(0,java_home.length()-3);
	    	String toolsjar=java_home+"lib"+File.separator+"tools.jar";
	    	java_home=java_home+"bin"+File.separator+"jstat.exe";
	  
	    	String jstatcmd="\""+java_home+"\""+" -snap "+id;
	    	System.out.println(jstatcmd);
	    	String agentJavahome=this.getAgentJVMHome(jstatcmd);
	    	System.out.println(agentJavahome);
	    	String loadAgentcmd=agentJavahome+ " -cp \""+agentJar+"\";\""+toolsjar+"\""+" com.websense.attach.SwingAgent "+agentJar+" "+id;
			System.out.println(loadAgentcmd);
	    	Process p;
			String message="";
		
			    try {
			      p = Runtime.getRuntime().exec(loadAgentcmd);

			      InputStream is = p.getInputStream();
			
			      InputStreamReader bi = new InputStreamReader(is);
			      BufferedReader br = new BufferedReader(bi);
			      
			      message =  br.readLine();      
			      while(message != null && !"".equals(message)){	
			        System.out.println(message);
			        if(message.equals("Attach to "+id+" successed!")){
			        	isSuccessed=true;
			        	break;
			        }
			        message =  br.readLine();
			      }
			    } catch (Exception e) {
			    	
			      e.printStackTrace();
			     
			    }
			    
	    	return isSuccessed;

	        
	  }
}
